//+---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation, 2007
//
// File: ConfigFileBase.cs
//
// Contents: Common helper methods for dealing with [assembly].config files
//
// Created by: adamland Dec 17, 2007
//
//----------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Globalization;

namespace Microsoft.Reputation.Services
{
    public class ConfigFileBase
    {
        public static string GetParameterValue(string parameterName, string defaultValue)
        {
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(parameterName));
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(defaultValue));

            using (TraceUtility.TraceMethod(
                Tracing.Source, 
                "parameterName={0}, defaultValue={1}", 
                parameterName, 
                defaultValue))
            {
                if (HasParameter(parameterName))
                {
                    return ConfigurationManager.AppSettings[parameterName];
                }
                else
                {
                    return defaultValue;
                }
            }
        }

        public static string GetStringWithNoDefault(string parameterName)
        {
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(parameterName));
            using (TraceUtility.TraceMethod(
                Tracing.Source,
                "parameterName={0}",
                parameterName))
            {
                if (HasParameter(parameterName))
                {
                    return ConfigurationManager.AppSettings[parameterName];
                }
                else
                {
                    BaseException baseEx = BaseException.Create(
                        CommonStrings.ErrorMessage_ConfigFileBase_ValueNotSpecified,
                        CommonStrings.ErrorMessage_ConfigFileBase_ValueCannotBeRetrieved,
                        parameterName);
                    TraceUtility.TraceThrowException(Tracing.Source, baseEx);
                    throw baseEx;
                }
            }
        }

        public static bool GetParameterValue(string parameterName, bool defaultValue)
        {
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(parameterName));

            using (TraceUtility.TraceMethod(
                Tracing.Source,
                "parameterName={0}, defaultValue={1}",
                parameterName,
                defaultValue))
            {
                if (HasParameter(parameterName))
                {
                    string valueAsString = ConfigurationManager.AppSettings[parameterName];
                    bool value;

                    if (bool.TryParse(valueAsString, out value))
                    {
                        return value;
                    }
                    else
                    {
                        throw GetAndTraceParsingException(parameterName, valueAsString);
                    }
                }
                else
                {
                    return defaultValue;
                }
            }
        }

        public static int GetParameterValue(string parameterName, int defaultValue, int minimum, int maximum)
        {
            using (TraceUtility.TraceMethod(
                Tracing.Source,
                "parameterName={0}, defaultValue={1}, minimum={2}, maximum={3}",
                parameterName,
                defaultValue,
                minimum,
                maximum))
            {
                if (parameterName == null)
                {
                    ArgumentNullException nullEx = new ArgumentNullException("parameterName");
                    TraceUtility.TraceThrowException(Tracing.Source, nullEx);
                    TraceUtility.TraceAssert(Tracing.Source, false, nullEx.Message);
                    throw nullEx;
                }
                if (minimum > maximum)
                {
                    ArgumentOutOfRangeException oorEx = new ArgumentOutOfRangeException(
                        "minimum",
                        minimum,
                        string.Format(
                            CultureInfo.CurrentCulture,
                            CommonStrings.ErrorMessage_ConfigFileBase_MinGreaterThanMax,
                            maximum));
                    TraceUtility.TraceThrowException(Tracing.Source, oorEx);
                    TraceUtility.TraceAssert(Tracing.Source, false, oorEx.Message);
                    throw oorEx;
                }
                if (defaultValue < minimum)
                {
                    ArgumentOutOfRangeException oorEx = new ArgumentOutOfRangeException(
                        "defaultValue",
                        defaultValue,
                        string.Format(
                            CultureInfo.CurrentCulture,
                            CommonStrings.ErrorMessage_ConfigFileBase_DefaultLowerThanMin,
                            minimum));
                    TraceUtility.TraceThrowException(Tracing.Source, oorEx);
                    TraceUtility.TraceAssert(Tracing.Source, false, oorEx.Message);
                    throw oorEx;
                }
                if (defaultValue > maximum)
                {
                    ArgumentOutOfRangeException oorEx = new ArgumentOutOfRangeException(
                        "defaultValue",
                        defaultValue,
                        string.Format(
                            CultureInfo.CurrentCulture,
                            CommonStrings.ErrorMessage_ConfigFileBase_DefaultGreaterThanMax,
                            maximum));
                    TraceUtility.TraceThrowException(Tracing.Source, oorEx);
                    TraceUtility.TraceAssert(Tracing.Source, false, oorEx.Message);
                    throw oorEx;
                }
                int value = GetParameterValue(parameterName, defaultValue);
                if (value < minimum)
                {
                    BaseException baseEx = BaseException.Create(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            CommonStrings.ErrorMessage_ConfigFileBase_ValueLowerThanMin,
                            value,
                            minimum),
                        CommonStrings.ErrorMessage_ConfigFileBase_ValueLowerThanMin_Operation,
                        parameterName);
                    TraceUtility.TraceThrowException(Tracing.Source, baseEx);
                    throw baseEx;
                }
                if (value > maximum)
                {
                    BaseException baseEx = BaseException.Create(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            CommonStrings.ErrorMessage_ConfigFileBase_ValueGreaterThanMax,
                            value,
                            maximum),
                        CommonStrings.ErrorMessage_ConfigFileBase_ValueGreaterThanMax_Operation,
                        parameterName);
                    TraceUtility.TraceThrowException(Tracing.Source, baseEx);
                    throw baseEx;
                }
                return value;
            }
        }

        public static int GetParameterValue(string parameterName, int defaultValue)
        {
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(parameterName));

            using (TraceUtility.TraceMethod(
                Tracing.Source,
                "parameterName={0}, defaultValue={1}",
                parameterName,
                defaultValue))
            {
                if (HasParameter(parameterName))
                {
                    string valueAsString = ConfigurationManager.AppSettings[parameterName];
                    int value;

                    if (int.TryParse(valueAsString, out value))
                    {
                        return value;
                    }
                    else
                    {
                        throw GetAndTraceParsingException(parameterName, valueAsString);
                    }
                }
                else
                {
                    return defaultValue;
                }
            }
        }

        private static BaseException GetAndTraceParsingException(string parameterName, string value)
        {
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(parameterName));

            using (TraceUtility.TraceMethod(
                Tracing.Source,
                "parameterName={0}, value={1}",
                parameterName,
                value))
            {
                BaseException ex = BaseException.Create(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        CommonStrings.ErrorMessage_ConfigFileBase_ValueCannotBeParsed,
                        value),
                    CommonStrings.ErrorMessage_ConfigFileBase_ValueCannotBeRetrieved,
                    parameterName);
                TraceUtility.TraceThrowException(Tracing.Source, ex);
                return ex;
            }
        }

        private static bool HasParameter(string parameterName)
        {
            TraceUtility.TraceAssert(Tracing.Source, !String.IsNullOrEmpty(parameterName));

            using (TraceUtility.TraceMethod(Tracing.Source, "parameterName={0}", parameterName))
            {
                foreach (string key in ConfigurationManager.AppSettings.Keys)
                {
                    if (String.IsNullOrEmpty(parameterName) == false
                        && parameterName.Equals(key, StringComparison.OrdinalIgnoreCase))
                    {
                        return true;
                    }
                }

                return false;
            }
        }
    }
}
